/*
 * © 2024 huayunliufeng保留所有权利, 依据MIT许可证发布。
 * 请勿更改或删除版权声明或此文件头。
 * 此代码是免费软件, 您可以重新分发和/或修改它。
 * 开源是希望它有用, 但不对代码做任何保证。
 * 如有疑问请联系: huayunliufeng@163.com
 */

package io.github.huayunliufeng.common.constant;

/**
 * 时间单位的枚举。如果使用long或double来表示纳秒, 最大是106751.99116730064天, 大约292年。
 *
 * @author zhongq 2024/5/30 15:53
 * @version 0.0.7
 * @since 0.0.7
 */
public enum TimeUnitEnum {
    /**
     * 纳秒 ns
     */
    NS,

    /**
     * 微秒, 1µs = 1,000ns
     */
    US,

    /**
     * 毫秒, 1ms = 1,000µs
     */
    MS,

    /**
     * 秒 , 1s = 1,000ms
     */
    S,

    /**
     * 分, 1min = 60s
     */
    M,

    /**
     * 时, 1h = 60min
     */
    H,

    /**
     * 天, 1d = 24h
     */
    D;

    /**
     * 将当前时间转换为指定的时间类型
     *
     * @param time time
     * @param src  当前时间单位
     * @param dst  目标时间单位
     * @return double
     */
    public static double timeConvert(double time, TimeUnitEnum src, TimeUnitEnum dst) {
        long l = timeToNs(time, src);
        return nsTimeTo(l, dst);
    }

    /**
     * 将时间转换为纳秒
     *
     * @param time time
     * @param src  当前时间单位
     * @return ns
     */
    public static long timeToNs(double time, TimeUnitEnum src) {
        switch (src) {
            case NS:
                return (long) time;
            case US:
                return (long) (time * 1000);
            case MS:
                return (long) (time * 1000_000);
            case S:
                return (long) (time * 1000_000_000);
            case M:
                return (long) (time * 1000_000_000 * 60);
            case H:
                return (long) (time * 1000_000_000 * 60 * 60);
            case D:
                return (long) (time * 1000_000_000 * 60 * 60 * 24);
            default:
                throw new RuntimeException("未知的时间单位。");
        }
    }

    /**
     * 将纳秒转换为指定单位的时间
     *
     * @param time time
     * @param dst  目标时间单位
     * @return double
     */
    public static double nsTimeTo(long time, TimeUnitEnum dst) {
        switch (dst) {
            case NS:
                return time;
            case US:
                return time / 1000.0;
            case MS:
                return time / 1000_000.0;
            case S:
                return time / 1000_000_000.0;
            case M:
                return time / (1000_000_000.0 * 60);
            case H:
                return time / (1000_000_000.0 * 60 * 60.0);
            case D:
                return time / (1000_000_000.0 * 60 * 60 * 24);
            default:
                throw new RuntimeException("未知的时间单位。");
        }
    }
}
